package com.donn.securitycontrolplatform.utils;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSONObject;
import com.dahuatech.hutool.http.Method;
import com.dahuatech.hutool.json.JSONUtil;
import com.dahuatech.icc.exception.ClientException;
import com.dahuatech.icc.multiinone.accesscontrol.AccessAuthByPersonSDK;
import com.dahuatech.icc.multiinone.accesscontrol.domain.CardPrivilege;
import com.dahuatech.icc.multiinone.accesscontrol.vo.AccessAuthByPersonRequest;
import com.dahuatech.icc.multiinone.brm.AddPersonCardSDK;
import com.dahuatech.icc.multiinone.brm.domain.CardInfo;
import com.dahuatech.icc.multiinone.brm.domain.PersonInfo;
import com.dahuatech.icc.multiinone.brm.vo.AddPersonCardRequest;
import com.dahuatech.icc.multiinone.brm.vo.AddPersonCardResponse;
import com.dahuatech.icc.multiinone.vo.BaseResponse;
import com.dahuatech.icc.oauth.http.DefaultClient;
import com.dahuatech.icc.oauth.http.IClient;
import com.dahuatech.icc.oauth.http.IccClient;
import com.dahuatech.icc.oauth.model.v202010.GeneralRequest;
import com.dahuatech.icc.oauth.model.v202010.GeneralResponse;
import com.dahuatech.icc.oauth.model.v202010.OauthConfigUserPwdInfo;
import com.donn.securitycontrolplatform.emum.RESULT_CODE;
import com.donn.securitycontrolplatform.expection.BusinessException;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.crypto.Cipher;
import java.io.File;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 大华相关工具类
 */
@Component
@Slf4j
public class DaHuaUtil {
    @Autowired
    RestTemplate restTemplate;


    /**
     * 请求公钥url
     */
    public static final String PUBLIC_KEY_URL = "/evo-apigw/evo-oauth/1.0.0/oauth/public-key";

    /**
     * 请求认证url
     */
    public static final String AUTHENTICATE_URL = "/evo-apigw/evo-oauth/1.0.0/oauth/extend/token";


    /**
     * 刷新toekn url
     */
    public static final String REFRESH_TOKEN_URL = "/evo-apigw/evo-oauth/1.0.0/oauth/extend/refresh/token";


    /**
     * 删除门禁授权
     */
    public static final String DELETE_MJ_URL = "/evo-apigw/evo-accesscontrol/${version}/card/accessControl/doorAuthority/delete/batch";


    /**
     * 用户保活 url
     */
    public static final String USER_KEEPALIVE_URL = "/evo-apigw/evo-brm/1.2.0/user/keepalive";


    /**
     * 人员新增接口(黑白名单库中添加人像)、facepath为调用图片上传接口返回的字符串;
     */
    public static final String ADD_USER_TO_URL = "/evo-apigw/evo-face/personInfo/add";

    /**
     * 修改人员信息
     */
    public static final String UPDATE_URL = "/evo-apigw/evo-face/personInfo/update";

    /**
     * 新增人像库
     */
    public static final String ADD_USER_STORE_URL = "/evo-apigw/evo-face/groupInfo/add";

    /**
     * 获取白名单人像库URL
     */
    public static final String GET_WHITE_LIST_USER_STORE_URL = "/evo-apigw/evo-face/groupInfo/page";

    /**
     * 人员图片上传URL
     */
    public static final String USER_PHOTO_UPLOAD_URL = "/evo-apigw/evo-face/personInfo/uploadPic";

    //大华client_id
    public static final String CLIENT_ID = "donn_web";
    //大华client secret
    public static final String CLIENT_SECRET = "5611e48c-5a3b-4fb5-86a6-f3ed8437304f";

    //大华连接用户名
    public static final String USER_NAME = "system";
    //大华连接密码
    public static final String PASSWORD = "Admin123";

    public static final String HTTPS = "443";//https 默认端口443，做了内外网映射 20033
    public static final String HTTP = "83";//https 默认端口443，做了内外网映射 20033


    //大华删除人员
    public static final String DELETE_USER_URL = "/evo-apigw/evo-face/personInfo/delete/";
    public static final String USER_FACE_PATH = "C:/RPM_deliver-scjg/frontend/html/dist/";
    /**
     * 成功状态码
     */
    public static final String SUCCESS_CODE = "0";

    public static final String CODE = "code";
    public static final String DATA = "data";
    public static final String PAGE_DATA = "pageData";
    public static final String IVSS_GROUP_REL_LIST = "ivssGroupRelList";
    public static final String GROUP_ID = "groupId";
    public static final String ACCESS_TOKEN = "access_token";
    public static final String REFRESH_TOKEN = "refresh_token";
    public static final String MAGI_CID = "magicId";
    public static final String TOTAL_ROWS = "totalRows";
    public static final String ACCESS_TYPE = "access_type";
    public static final String HOST = "192.168.253.200";


    /**
     * 根据personId添加人员到门禁
     */
    public void authByPersonId(Long personId, Long quantumId) {
        OauthConfigUserPwdInfo oauthConfigBaseInfo = new OauthConfigUserPwdInfo(DaHuaUtil.HOST, DaHuaUtil.CLIENT_ID, DaHuaUtil.CLIENT_SECRET, DaHuaUtil.USER_NAME, DaHuaUtil.PASSWORD, false, HTTPS, HTTP);
        AccessAuthByPersonSDK accessAuthByPersonSDK = new AccessAuthByPersonSDK();
        AccessAuthByPersonRequest accessAuthByPersonRequest = new AccessAuthByPersonRequest();
        accessAuthByPersonRequest.setOauthConfigBaseInfo(oauthConfigBaseInfo);
        accessAuthByPersonRequest.setPersonId(personId);
        accessAuthByPersonRequest.setTimeQuantumId(1l);
        List<CardPrivilege> list = new ArrayList<CardPrivilege>();
        CardPrivilege cardPrivilege = new CardPrivilege();
        cardPrivilege.setPrivilegeType("2");
        cardPrivilege.setResouceCode("们组id");
        list.add(cardPrivilege);
        accessAuthByPersonRequest.setCardPrivilegeDetails(list);
        BaseResponse baseResponse = accessAuthByPersonSDK.auth(accessAuthByPersonRequest);
        System.out.println("添加人员到门禁成功=" + JSONUtil.toJsonStr(baseResponse));
    }


    public static String userpwdAuth() throws ClientException {
        OauthConfigUserPwdInfo oauthConfigBaseInfo = new OauthConfigUserPwdInfo(HOST, CLIENT_ID, CLIENT_SECRET, USER_NAME, PASSWORD, false, HTTPS, HTTP);
        IccClient iccClient = new IccClient(oauthConfigBaseInfo);
        System.out.println(iccClient.getAccessToken());
        return iccClient.getAccessToken().getAccess_token();
    }


    /**
     * @return 获取白名单库的id 若没有则创建一个再返回库id
     * @throws BusinessException
     */
    public Long getWhiteListUserStore() throws BusinessException, ClientException {
        IClient iClient = iccDefaultClient();
        GeneralRequest generalRequest = new GeneralRequest(DaHuaUtil.GET_WHITE_LIST_USER_STORE_URL, Method.GET);
        // set http post body
        generalRequest.form("pageNum", 1);
        generalRequest.form("pageSize", 10);
        generalRequest.form("searchType", 2);
        generalRequest.form("pageNum", 1);
        generalRequest.form("grouptype", 1);

        // set header
//            generalRequest.header("key", "value");
        // 发起请求处理应答
        GeneralResponse generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
        checkResponse(generalResponse.getCode(), generalResponse.getErrMsg());
        String response = generalResponse.getResult();
        log.info("response=" + response);
        JsonObject responseJsonObject = getResponseJsonObject(response);
        JsonObject dataObject = responseJsonObject.getAsJsonObject(DATA);
        log.info("dataObject=" + dataObject);


        long totalRows = dataObject.get(TOTAL_ROWS).getAsLong();

        if (0 == totalRows) {
            //没有找到白名库 则创建一个白名单库
            addUserStore("人像白名单库,用于放行门禁录入的人像", "人像白名单库", 1);
            getWhiteListUserStore();
        }


//        JsonArray asJsonArray = dataObject.getAsJsonObject(IVSS_GROUP_REL_LIST).getAsJsonArray();

        return dataObject.getAsJsonArray("pageData").get(0).getAsJsonObject().getAsJsonArray(IVSS_GROUP_REL_LIST).get(0).getAsJsonObject().get(GROUP_ID).getAsLong();


    }


    /**
     * 人员图片上传 返回上传后图片的相对路径
     *
     * @throws ClientException
     */
    public String addUserPhoto(String fileName, String photoBase64) throws ClientException, BusinessException {
        IClient iClient = iccDefaultClient();
        GeneralRequest generalRequest = new GeneralRequest(DaHuaUtil.USER_PHOTO_UPLOAD_URL, Method.POST);
        Map<String, String> map = new HashMap<>();
        map.put("fileName", fileName);
        map.put("img", photoBase64);
        // set http post body
        generalRequest.body(JSONUtils.toJSONString(map));
        // 发起请求处理应答
        GeneralResponse generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
        checkResponse(generalResponse.getCode(), generalResponse.getErrMsg());
        JsonObject responseJsonObject = getResponseJsonObject(generalResponse.getResult());

        String dataObject = responseJsonObject.get(DATA).getAsString();

        return dataObject;


    }


    /**
     * 新增人像库
     *
     * @return
     */
    public boolean addUserStore(String groupdetail, String groupname, Integer grouptype) throws BusinessException, ClientException {
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("groupdetail", groupdetail);
        requestBody.put("groupname", groupname);
        requestBody.put("grouptype", grouptype);

        IClient iClient = iccDefaultClient();
        /**
         * 1、请求地址是统一网关入口，以 /evo-apigw 开头
         * 2、方法参见 @see com.dahuatech.hutool.http.Method
         */
        GeneralRequest generalRequest = new GeneralRequest(DaHuaUtil.ADD_USER_STORE_URL, Method.POST);
        // set http post body
        generalRequest.body(JSONUtils.toJSONString(requestBody));

        // set header
//            generalRequest.header("key", "value");
        // 发起请求处理应答
        GeneralResponse generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
        checkResponse(generalResponse.getCode(), generalResponse.getErrMsg());
        return true;
    }


    /**
     * 从身份证号码解析生日 年月日 xxxx-xx-xx
     *
     * @param birthday
     * @return
     */
    public String generateBirthday(String birthday) {
        String year = birthday.substring(6, 10);
        String month = birthday.substring(10, 12);
        String day = birthday.substring(12, 14);
        StringBuilder sb = new StringBuilder();
        sb.append(year).append("-").append(month).append("-").append(day);
        return sb.toString();
    }


    /**
     * @param name     姓名
     * @param sex      性别
     * @param cardtype 证件类型
     * @param cardid   证件号码
     * @param groupid  人像注册库id
     * @param birthday 出生日期
     * @param facepath 图片相对路径 值为通过人员图片上传接口返回值
     */
    public Long addUser(String name, Integer sex, String cardtype, String cardid, Long groupid, String birthday, String facepath) throws BusinessException, ClientException {
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("name", name);
        requestBody.put("sex", sex);
        requestBody.put("cardtype", cardtype);
        requestBody.put("cardid", cardid);
        requestBody.put("groupid", groupid);
        requestBody.put("birthday", birthday);
        requestBody.put("facepath", facepath);
        IClient iClient = iccDefaultClient();
        /**
         * 1、请求地址是统一网关入口，以 /evo-apigw 开头
         * 2、方法参见 @see com.dahuatech.hutool.http.Method
         */
        GeneralRequest generalRequest = new GeneralRequest(DaHuaUtil.ADD_USER_TO_URL, Method.POST);
        // set http post body
        generalRequest.body(JSONUtils.toJSONString(requestBody));
        GeneralResponse generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
        checkResponse(generalResponse.getCode(), generalResponse.getErrMsg());
        JsonObject responseJsonObject = getResponseJsonObject(generalResponse.getResult());

        Long personId = responseJsonObject.get(DATA).getAsLong();
        return personId;
    }


    /**
     * 用户保活
     *
     * @return
     */
    public Boolean userKeepalive(Integer clientType, String magicId) {
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("clientType", clientType);
        requestBody.put("magicId", magicId);
        String response = restTemplate.postForObject(USER_KEEPALIVE_URL, JSONUtils.toJSONString(requestBody), String.class);
        return checkResponse(getResponseJsonObject(response));
    }


    /**
     * 获取鉴权公钥信息
     */
    public String getPublicKey() {
        String response = restTemplate.getForObject(PUBLIC_KEY_URL, String.class);
        JsonElement jsonElement = JsonParser.parseString(response);
        JsonObject asJsonObject = jsonElement.getAsJsonObject();
        JsonElement data = asJsonObject.getAsJsonObject("data");//获取公钥部分信息
        JsonObject publicKeyObject = data.getAsJsonObject();
        String publicKey = publicKeyObject.getAsString();
        return publicKey;
    }


    /**
     * 获取认证
     *
     * @return
     */
    public Map<String, String> getAuthenticate(String grant_type, String username, String password, String client_id, String client_secret, String public_key) throws BusinessException {
        JSONObject postData = new JSONObject();
        postData.put("grant_type", grant_type);
        postData.put("username", username);
        postData.put("password", password);
        postData.put("client_id", client_id);
        postData.put("client_secret", client_secret);
        postData.put("public_key", public_key);
        String response = restTemplate.postForObject(AUTHENTICATE_URL, JSONUtils.toJSONString(postData), String.class);
        JsonObject responseJsonObject = getResponseJsonObject(response);
        if (!checkResponse(responseJsonObject)) throw new BusinessException(RESULT_CODE.DAHUA_GET_AUTHENTICATE_FAIL);

        String accessToken = responseJsonObject.getAsJsonObject(DATA).getAsJsonObject(ACCESS_TOKEN).getAsString();
        String refreshToken = responseJsonObject.getAsJsonObject(DATA).getAsJsonObject(REFRESH_TOKEN).getAsString();
        String magiCid = responseJsonObject.getAsJsonObject(DATA).getAsJsonObject(MAGI_CID).getAsString();

        Map<String, String> responseMap = new HashMap<>();
        responseMap.put("accessToken", accessToken);
        responseMap.put("refreshToken", refreshToken);
        responseMap.put("magiCid", magiCid);

        return responseMap;
    }


    /**
     * 检查返回状态是否成功
     *
     * @param asJsonObject
     * @return
     */
    public static boolean checkResponse(JsonObject asJsonObject) {
        String responseCode = asJsonObject.getAsJsonObject(CODE).getAsString();
        return SUCCESS_CODE.equals(responseCode);
    }

    /**
     * 检查返回状态是否成功 否则抛出异常
     *
     * @param responseCode
     * @return
     */
    public static void checkResponse(String responseCode, String responseErrmsg) throws BusinessException {
        if (!"0".equals(responseCode))
            throw new BusinessException(Integer.parseInt(responseCode), responseErrmsg);
    }

    /**
     * 获取请求返回的json对象
     *
     * @param response
     * @return
     */
    public static JsonObject getResponseJsonObject(String response) {
        JsonElement jsonElement = JsonParser.parseString(response);
        JsonObject asJsonObject = jsonElement.getAsJsonObject();
        return asJsonObject;
    }


    /**
     * 刷新token
     *
     * @return
     */
    public String refreshToken(String grant_type, String client_id, String client_secret, String refresh_token) throws BusinessException {
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("grant_type", grant_type);
        requestBody.put("client_id", client_id);
        requestBody.put("client_secret", client_secret);
        requestBody.put("refresh_token", refresh_token);
        String response = restTemplate.postForObject(REFRESH_TOKEN_URL, JSONUtils.toJSONString(requestBody), String.class);
        JsonObject responseJsonObject = getResponseJsonObject(response);
        if (!checkResponse(responseJsonObject)) throw new BusinessException(RESULT_CODE.DAHUA_REFRESH_TOKEN_FAIL);

        return "";
    }

    /**
     * RSA公钥加密
     *
     * @param password  待加密的密码
     * @param publicKey 公钥
     * @return 密文
     */
    public static String encryptRSA(String password, String publicKey) {
        // base64编码的公钥
        try {
            byte[] decoded = Base64.decode(publicKey);
            RSAPublicKey pubKey =
                    (RSAPublicKey)
                            KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
            // RSA加密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            //**此处Base64编码，开发者可以使用自己的库**
            String outStr = Base64.encode(cipher.doFinal(password.getBytes("UTF-8")));
            return outStr;
        } catch (Exception e) {

        }
        return null;
    }


    //如果你项目没有办法增加iccSdk.properties配置文件，你也可以
    public IClient iccDefaultClient() throws ClientException {
        return new DefaultClient(HOST, USER_NAME, PASSWORD, CLIENT_ID, CLIENT_SECRET);
    }


    /**
     * 同步删除大华人脸白名单信息
     *
     * @param personid
     * @param groupid
     */
    public void deleteUser(Long personid, Long groupid) throws ClientException, BusinessException {
        IClient iClient = iccDefaultClient();
        String requestURL = DaHuaUtil.DELETE_USER_URL + personid + "/" + groupid;
        GeneralRequest generalRequest = new GeneralRequest(requestURL, Method.GET);
        // 发起请求处理应答
        GeneralResponse generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
        checkResponse(generalResponse.getCode(), generalResponse.getErrMsg());
    }


    /**
     * 同步更改大华人脸白名单信息
     *
     * @param personid
     * @param name
     * @param sex
     * @param cardtype
     * @param cardid
     * @param groupid
     * @param birthday
     * @param facepath
     * @throws ClientException
     * @throws BusinessException
     */
    public void updateUser(Long personid, String name, Integer sex, String cardtype, String cardid, Long groupid, String birthday, String facepath) throws ClientException, BusinessException {
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("personid", personid);
        requestBody.put("name", name);
        requestBody.put("sex", sex);
        requestBody.put("cardtype", cardtype);
        requestBody.put("cardid", cardid);
        requestBody.put("groupid", groupid);
        requestBody.put("birthday", birthday);
        requestBody.put("facepath", facepath);


        IClient iClient = iccDefaultClient();
        GeneralRequest generalRequest = new GeneralRequest(UPDATE_URL, Method.POST);
        generalRequest.body(JSONUtils.toJSONString(requestBody));
        // 发起请求处理应答
        GeneralResponse generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
        checkResponse(generalResponse.getCode(), generalResponse.getErrMsg());
    }


    public Map<String, Object> addPersonAndCards(String name, String idno, String file, String startDate, String endDate) throws ClientException {
        AddPersonCardSDK userCardSDK = new AddPersonCardSDK();
        OauthConfigUserPwdInfo oauthConfigBaseInfo = new OauthConfigUserPwdInfo(HOST, CLIENT_ID, CLIENT_SECRET, USER_NAME, PASSWORD, false, HTTPS, HTTP);
        AddPersonCardRequest addPersonCardRequest = new AddPersonCardRequest();
        addPersonCardRequest.setOauthConfigBaseInfo(oauthConfigBaseInfo);
        addPersonCardRequest.setPersonInfo(buildPersonInfo(name, idno, file));
        addPersonCardRequest.setCards(buildCards(startDate, endDate));
        AddPersonCardResponse addPersonCardResponse = userCardSDK.addPersonAndCards(addPersonCardRequest);


        Map<String, Object> map = new HashMap<>();
        map.put("personId", addPersonCardResponse.getPersonId());
        map.put("cards", addPersonCardRequest.getCards());
        return map;

    }

    private PersonInfo buildPersonInfo(String name, String idno, String file) {


        PersonInfo personInfo = new PersonInfo();
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        Date date = new Date();
        personInfo.setCode("code" + dateFormat.format(date));
        personInfo.setName("name" + dateFormat.format(date));
        personInfo.setPaperType(111);
        personInfo.setPaperNumber(idno);
        personInfo.setPaperAddress("四川省绵阳市");
        personInfo.setFaceImage(new File(file));
        return personInfo;
    }

    private List<CardInfo> buildCards(String startDate, String endDate) {
        List<CardInfo> list = new ArrayList<CardInfo>();
        Calendar calendar = Calendar.getInstance();
        DateFormat dateFormat = new SimpleDateFormat("MMddHHmmss");
        CardInfo cardInfo = new CardInfo();
//        cardInfo.setStartDate(startDate);
//        cardInfo.setEndDate(endDate);


        DateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        cardInfo.setStartDate(dateFormat1.format(calendar.getTime()));
        calendar.add(Calendar.YEAR,2);
        cardInfo.setEndDate(dateFormat1.format(calendar.getTime()));
        cardInfo.setCardNumber(dateFormat.format(calendar.getTime()) + "01");
        cardInfo.setCategory("0");
        list.add(cardInfo);
        return list;
    }

    public void deleteMj(String cardNumber) throws ClientException, BusinessException {
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("cardNums", Arrays.asList(cardNumber));
        requestBody.put("privilegeType", "3");

        IClient iClient = iccDefaultClient();
        GeneralRequest generalRequest = new GeneralRequest(DELETE_MJ_URL, Method.POST);
        generalRequest.body(JSONUtils.toJSONString(requestBody));
        // 发起请求处理应答
        GeneralResponse generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
        checkResponse(generalResponse.getCode(), generalResponse.getErrMsg());
    }
}
